/**
 * Copyright (c) 2021-2024 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef PLUGINS_ECMASCRIPT_RUNTIME_INTRINSICS_INL_H
#define PLUGINS_ECMASCRIPT_RUNTIME_INTRINSICS_INL_H

#include <limits>
#include "intrinsics.h"

#include "macros.h"
#include "runtime/include/method-inl.h"
#include "plugins/ecmascript/runtime/js_tagged_value-inl.h"
#include "plugins/ecmascript/runtime/interpreter/slow_runtime_stub.h"
#include "plugins/ecmascript/runtime/interpreter/interpreter-inl.h"
#include "plugins/ecmascript/runtime/interpreter/fast_runtime_stub-inl.h"
#include "plugins/ecmascript/compiler/ecmascript_extensions/thread_environment_api.h"
#include "plugins/ecmascript/runtime/ic/ic_runtime_stub-inl.h"
#include "plugins/ecmascript/runtime/ic/profile_type_info.h"
#include "plugins/ecmascript/runtime/js_generator_object.h"
#include "plugins/ecmascript/runtime/js_handle.h"
#include "plugins/ecmascript/runtime/js_array.h"
#include "plugins/ecmascript/runtime/js_eval.h"

namespace ark::ecmascript::intrinsics {
#ifndef INLINE_ECMA_INTRINSICS
#define INLINE_ECMA_INTRINSICS ALWAYS_INLINE inline
#endif

#if ECMASCRIPT_ENABLE_IC
static inline JSTaggedValue GetRuntimeProfileTypeInfo(JSFunction *func)
{
    return func->GetProfileTypeInfo();
}
#endif

template <bool THIS_CALL = false>
static inline JSTaggedValue HandlerCall(JSThread *thread, EcmaRuntimeCallInfo *info, JSTaggedValue fnObject)
{
    if (UNLIKELY(!fnObject.IsCallable())) {
        [[maybe_unused]] EcmaHandleScope handleScope(thread);
        JSHandle<JSObject> error = GetFactory(thread)->GetJSError(ErrorType::TYPE_ERROR, "is not callable");
        thread->SetException(error.GetTaggedValue());
        return JSTaggedValue(JSTaggedValue::VALUE_EXCEPTION);
    }

    ECMAObject *jsObject = ECMAObject::Cast(fnObject.GetHeapObject());
    Method *method = jsObject->GetCallTarget();

    // NOLINTNEXTLINE(readability-braces-around-statements, bugprone-suspicious-semicolon)
    if constexpr (!THIS_CALL) {
        ASSERT(info->GetThis().GetTaggedValue() == JSTaggedValue::Undefined());
        if (fnObject.IsJSFunction() && !JSFunction::Cast(jsObject)->IsStrict()) {
            // Set this=GlobalObject for sloppy function
            info->SetThis(thread->GetEcmaVM()->GetGlobalEnv()->GetGlobalObject());
        }
    }

    if (method->IsNative()) {
        ASSERT(method->GetNumVregs() == 0);

        LOG(DEBUG, INTERPRETER) << "Native function";

        LOG(DEBUG, INTERPRETER) << "Entry: Runtime Call.";
        JSTaggedValue retValue = EcmaInterpreter::ExecuteNative(info);
        if (UNLIKELY(thread->HasPendingException())) {
            return JSTaggedValue::Exception();
        }
        LOG(DEBUG, INTERPRETER) << "Exit: Runtime Call.";
        return retValue;
    }

    JSFunction *jsFunction = JSFunction::Cast(jsObject);
    if (UNLIKELY(jsFunction->IsClassConstructor())) {
        [[maybe_unused]] EcmaHandleScope handleScope(thread);
        JSHandle<JSObject> error = thread->GetEcmaVM()->GetFactory()->GetJSError(
            ErrorType::TYPE_ERROR, "class constructor cannot called without 'new'");
        thread->SetException(error.GetTaggedValue());
        return JSTaggedValue::Exception();
    }

    LOG(DEBUG, INTERPRETER) << "Method name: " << method->GetName().data;
    JSTaggedValue retValue = EcmaInterpreter::ExecuteInvoke(info, fnObject);

    if (UNLIKELY(thread->HasPendingException())) {
        return JSTaggedValue::Exception();
    }
    return retValue;
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t Ldnan()
{
    return JSTaggedValue(base::NAN_VALUE).GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t Ldinfinity()
{
    return JSTaggedValue(base::POSITIVE_INFINITY).GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t Ldglobalthis(JSThread *thread)
{
    return GetGlobalObject(thread).GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t Ldundefined()
{
    return JSTaggedValue::Undefined().GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t Ldboolean([[maybe_unused]] JSThread *thread, [[maybe_unused]] uint64_t a0)
{
    UNREACHABLE();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t Ldnumber([[maybe_unused]] JSThread *thread, [[maybe_unused]] uint64_t a0)
{
    UNREACHABLE();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t Ldstring([[maybe_unused]] JSThread *thread, [[maybe_unused]] uint64_t a0)
{
    UNREACHABLE();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t Ldbigint([[maybe_unused]] JSThread *thread, [[maybe_unused]] uint64_t numberBigInt)
{
    INTERPRETER_TRACE(thread, Ldbigint);
    [[maybe_unused]] EcmaHandleScope handleScope(thread);
    JSHandle<JSTaggedValue> bigIntHandle(thread, JSTaggedValue(numberBigInt));
    return JSTaggedValue::ToBigInt(thread, bigIntHandle).GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t Ldnull()
{
    return JSTaggedValue::Null().GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t Ldsymbol(JSThread *thread)
{
    return GetGlobalEnv(thread)->GetSymbolFunction().GetTaggedValue().GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t Ldobject([[maybe_unused]] JSThread *thread, [[maybe_unused]] uint64_t a0,
                                         [[maybe_unused]] uint64_t a1)
{
    UNREACHABLE();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t Ldfunction([[maybe_unused]] JSThread *thread, [[maybe_unused]] uint64_t a0,
                                           [[maybe_unused]] uint64_t a1)
{
    UNREACHABLE();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t Ldtrue()
{
    return JSTaggedValue::True().GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t Ldfalse()
{
    return JSTaggedValue::False().GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t Add2Dyn(JSThread *thread, uint64_t lhs, uint64_t rhs)
{
    auto left = JSTaggedValue(lhs);
    auto right = JSTaggedValue(rhs);

    if (left.IsInt() && right.IsInt()) {
        int32_t a0 = left.GetInt();
        int32_t a1 = right.GetInt();
        if ((a0 > 0 && a1 > INT32_MAX - a0) || (a0 < 0 && a1 < INT32_MIN - a0)) {
            auto ret = static_cast<double>(a0) + static_cast<double>(a1);
            return JSTaggedValue(ret).GetRawData();
        }
        return JSTaggedValue(a0 + a1).GetRawData();
    }
    if (left.IsNumber() && right.IsNumber()) {
        double a0Double = left.IsInt() ? left.GetInt() : left.GetDouble();
        double a1Double = right.IsInt() ? right.GetInt() : right.GetDouble();
        return JSTaggedValue(a0Double + a1Double).GetRawData();
    }
    auto ecmaVm = thread->GetEcmaVM();
    return SlowRuntimeStub::Add2Dyn(thread, ecmaVm, left, right).GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t Sub2Dyn(JSThread *thread, uint64_t lhs, uint64_t rhs)
{
    auto left = JSTaggedValue(lhs);
    auto right = JSTaggedValue(rhs);

    if (left.IsInt() && right.IsInt()) {
        int32_t a0 = left.GetInt();
        int32_t a1 = -right.GetInt();
        if ((a0 > 0 && a1 > INT32_MAX - a0) || (a0 < 0 && a1 < INT32_MIN - a0)) {
            auto ret = static_cast<double>(a0) + static_cast<double>(a1);
            return JSTaggedValue(ret).GetRawData();
        }
        return JSTaggedValue(a0 + a1).GetRawData();
    }
    if (left.IsNumber() && right.IsNumber()) {
        double a0Double = left.IsInt() ? left.GetInt() : left.GetDouble();
        double a1Double = right.IsInt() ? right.GetInt() : right.GetDouble();
        return JSTaggedValue(a0Double - a1Double).GetRawData();
    }
    return SlowRuntimeStub::Sub2Dyn(thread, left, right).GetRawData();
}

// 12.6.3 Runtime Semantics: Evaluation
// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t Mul2Dyn(JSThread *thread, uint64_t lhs, uint64_t rhs)
{
    auto left = JSTaggedValue(lhs);
    auto right = JSTaggedValue(rhs);

    auto res = FastRuntimeStub::FastMul(left, right);
    if (!res.IsHole()) {
        return res.GetRawData();
    }
    return SlowRuntimeStub::Mul2Dyn(thread, left, right).GetRawData();
}

// 12.6.3 Runtime Semantics: Evaluation
// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t Div2Dyn(JSThread *thread, uint64_t lhs, uint64_t rhs)
{
    auto left = JSTaggedValue(lhs);
    auto right = JSTaggedValue(rhs);

    auto res = FastRuntimeStub::FastDiv(left, right);
    if (!res.IsHole()) {
        return res.GetRawData();
    }
    return SlowRuntimeStub::Div2Dyn(thread, left, right).GetRawData();
}

// 12.6.3 Runtime Semantics: Evaluation
// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t Mod2Dyn(JSThread *thread, uint64_t lhs, uint64_t rhs)
{
    auto left = JSTaggedValue(lhs);
    auto right = JSTaggedValue(rhs);

    auto res = FastRuntimeStub::FastMod(left, right);
    if (!res.IsHole()) {
        return res.GetRawData();
    }
    return SlowRuntimeStub::Mod2Dyn(thread, left, right).GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t ExpDyn(JSThread *thread, uint64_t baseExp, uint64_t exp)
{
    auto base = JSTaggedValue(baseExp);
    auto exponent = JSTaggedValue(exp);

    JSTaggedValue res;

    if (base.IsNumber() && exponent.IsNumber()) {
        double doubleBase = base.IsInt() ? base.GetInt() : base.GetDouble();
        double doubleExponent = exponent.IsInt() ? exponent.GetInt() : exponent.GetDouble();
        res = base::NumberHelper::Pow(doubleBase, doubleExponent);
    } else {
        res = SlowRuntimeStub::ExpDyn(thread, base, exponent);
    }
    return res.GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t EqDyn(JSThread *thread, uint64_t lhs, uint64_t rhs)
{
    auto left = JSTaggedValue(lhs);
    auto right = JSTaggedValue(rhs);

    auto res = FastRuntimeStub::FastEqual(left, right);
    if (!res.IsHole()) {
        return res.GetRawData();
    }
    return SlowRuntimeStub::EqDyn(thread, left, right).GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t NotEqDyn(JSThread *thread, uint64_t lhs, uint64_t rhs)
{
    auto left = JSTaggedValue(lhs);
    auto right = JSTaggedValue(rhs);

    auto res = FastRuntimeStub::FastEqual(left, right);
    if (!res.IsHole()) {
        return res.IsTrue() ? JSTaggedValue::False().GetRawData() : JSTaggedValue::True().GetRawData();
    }
    return SlowRuntimeStub::NotEqDyn(thread, left, right).GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t StrictEqDyn(JSThread *thread, uint64_t lhs, uint64_t rhs)
{
    auto left = JSTaggedValue(lhs);
    auto right = JSTaggedValue(rhs);
    return JSTaggedValue(FastRuntimeStub::FastStrictEqual(thread, left, right)).GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t StrictNotEqDyn(JSThread *thread, uint64_t lhs, uint64_t rhs)
{
    auto left = JSTaggedValue(lhs);
    auto right = JSTaggedValue(rhs);
    return JSTaggedValue(!FastRuntimeStub::FastStrictEqual(thread, left, right)).GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t LessDyn(JSThread *thread, uint64_t lhs, uint64_t rhs)
{
    auto left = JSTaggedValue(lhs);
    auto right = JSTaggedValue(rhs);

    if (left.IsNumber() && right.IsNumber()) {
        double valueA = left.IsInt() ? static_cast<double>(left.GetInt()) : left.GetDouble();
        double valueB = right.IsInt() ? static_cast<double>(right.GetInt()) : right.GetDouble();
        bool ret = JSTaggedValue::StrictNumberCompare(valueA, valueB) == ComparisonResult::LESS;
        return ret ? JSTaggedValue::True().GetRawData() : JSTaggedValue::False().GetRawData();
    }
    return SlowRuntimeStub::LessDyn(thread, left, right).GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t LessEqDyn(JSThread *thread, uint64_t lhs, uint64_t rhs)
{
    auto left = JSTaggedValue(lhs);
    auto right = JSTaggedValue(rhs);

    if (left.IsNumber() && right.IsNumber()) {
        double valueA = left.IsInt() ? static_cast<double>(left.GetInt()) : left.GetDouble();
        double valueB = right.IsInt() ? static_cast<double>(right.GetInt()) : right.GetDouble();
        bool ret = JSTaggedValue::StrictNumberCompare(valueA, valueB) <= ComparisonResult::EQUAL;
        return ret ? JSTaggedValue::True().GetRawData() : JSTaggedValue::False().GetRawData();
    }
    return SlowRuntimeStub::LessEqDyn(thread, left, right).GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t GreaterDyn(JSThread *thread, uint64_t lhs, uint64_t rhs)
{
    auto left = JSTaggedValue(lhs);
    auto right = JSTaggedValue(rhs);

    if (left.IsNumber() && right.IsNumber()) {
        double valueA = left.IsInt() ? static_cast<double>(left.GetInt()) : left.GetDouble();
        double valueB = right.IsInt() ? static_cast<double>(right.GetInt()) : right.GetDouble();
        bool ret = JSTaggedValue::StrictNumberCompare(valueA, valueB) == ComparisonResult::GREAT;
        return ret ? JSTaggedValue::True().GetRawData() : JSTaggedValue::False().GetRawData();
    }
    return SlowRuntimeStub::GreaterDyn(thread, left, right).GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t GreaterEqDyn(JSThread *thread, uint64_t lhs, uint64_t rhs)
{
    auto left = JSTaggedValue(lhs);
    auto right = JSTaggedValue(rhs);

    if (left.IsNumber() && right.IsNumber()) {
        double valueA = left.IsInt() ? static_cast<double>(left.GetInt()) : left.GetDouble();
        double valueB = right.IsInt() ? static_cast<double>(right.GetInt()) : right.GetDouble();
        ComparisonResult comparison = JSTaggedValue::StrictNumberCompare(valueA, valueB);
        bool ret = (comparison == ComparisonResult::GREAT) || (comparison == ComparisonResult::EQUAL);
        return ret ? JSTaggedValue::True().GetRawData() : JSTaggedValue::False().GetRawData();
    }
    return SlowRuntimeStub::GreaterEqDyn(thread, left, right).GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t TryLdGlobalByName(JSThread *thread, uint64_t prop, [[maybe_unused]] uint16_t slotId,
                                                  [[maybe_unused]] uint64_t func)
{
    JSTaggedType globalObj = GetGlobalObject(thread).GetRawData();
    JSTaggedValue result = JSTaggedValue::Hole();
    [[maybe_unused]] size_t gc = thread->GetEcmaVM()->GetGC()->GetCounter();
#if ECMASCRIPT_ENABLE_IC
    auto jsFunc = JSFunction::Cast(JSTaggedValue(func).GetHeapObject());
    if (ICRuntimeStub::HaveICForFunction(jsFunc)) {
        result = ICRuntimeStub::LoadGlobalICByName(thread, jsFunc, JSTaggedValue(globalObj), JSTaggedValue(prop),
                                                   slotId, true);
        if (!result.IsHole()) {
            return result.GetRawData();
        }
    }
#endif

    bool found = false;
    ASSERT_PRINT(gc == thread->GetEcmaVM()->GetGC()->GetCounter(), "GC happend where it is not supposed");
    result = FastRuntimeStub::GetGlobalOwnProperty(JSTaggedValue(globalObj), JSTaggedValue(prop), &found);
    if (found) {
        return result.GetRawData();
    }
    ASSERT_PRINT(gc == thread->GetEcmaVM()->GetGC()->GetCounter(), "GC happend where it is not supposed");
    return SlowRuntimeStub::TryLdGlobalByName(thread, JSTaggedValue(globalObj), JSTaggedValue(prop)).GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t Tonumber(JSThread *thread, uint64_t a0)
{
    auto value = JSTaggedValue(a0);
    if (value.IsNumber()) {
        return value.GetRawData();
    }
    return SlowRuntimeStub::ToNumber(thread, value).GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t NegDyn(JSThread *thread, uint64_t val)
{
    auto value = JSTaggedValue(val);

    if (value.IsInt()) {
        if (value.GetInt() == 0) {
            return JSTaggedValue(-0.0).GetRawData();
        }
        if (value.GetInt() == std::numeric_limits<int32_t>::min()) {
            return JSTaggedValue(std::numeric_limits<int32_t>::max() + 1.0).GetRawData();
        }
        return JSTaggedValue(-value.GetInt()).GetRawData();
    }
    if (value.IsDouble()) {
        return JSTaggedValue(-value.GetDouble()).GetRawData();
    }
    return SlowRuntimeStub::NegDyn(thread, value).GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t NotDyn(JSThread *thread, uint64_t val)
{
    auto value = JSTaggedValue(val);
    if (value.IsInt()) {
        auto number = static_cast<int32_t>(value.GetInt());
        return JSTaggedValue(~number).GetRawData();  // NOLINT(hicpp-signed-bitwise)
    }
    if (value.IsDouble()) {
        int32_t number = base::NumberHelper::DoubleToInt(value.GetDouble(), base::INT32_BITS);
        return JSTaggedValue(~number).GetRawData();  // NOLINT(hicpp-signed-bitwise)
    }
    return SlowRuntimeStub::NotDyn(thread, value).GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t IncDyn(JSThread *thread, uint64_t val)
{
    auto value = JSTaggedValue(val);

    if (value.IsInt()) {
        int32_t a0 = value.GetInt();
        if (UNLIKELY(a0 == INT32_MAX)) {
            return JSTaggedValue(static_cast<double>(a0) + 1.0).GetRawData();
        }
        return JSTaggedValue(a0 + 1).GetRawData();
    }
    if (value.IsDouble()) {
        return JSTaggedValue(value.GetDouble() + 1.0).GetRawData();
    }
    return SlowRuntimeStub::IncDyn(thread, value).GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t DecDyn(JSThread *thread, uint64_t val)
{
    auto value = JSTaggedValue(val);

    if (value.IsInt()) {
        int32_t a0 = value.GetInt();
        if (UNLIKELY(a0 == INT32_MIN)) {
            return JSTaggedValue(static_cast<double>(a0) - 1.0).GetRawData();
        }
        return JSTaggedValue(a0 - 1).GetRawData();
    }
    if (value.IsDouble()) {
        return JSTaggedValue(value.GetDouble() - 1.0).GetRawData();
    }
    return SlowRuntimeStub::DecDyn(thread, value).GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t Defineglobalvar([[maybe_unused]] JSThread *thread, [[maybe_unused]] uint64_t a0,
                                                [[maybe_unused]] uint64_t a1)
{
    UNREACHABLE();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t Definelocalvar([[maybe_unused]] JSThread *thread, [[maybe_unused]] uint64_t a0,
                                               [[maybe_unused]] uint64_t a1)
{
    UNREACHABLE();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t Definefuncexpr([[maybe_unused]] JSThread *thread, [[maybe_unused]] uint64_t a0,
                                               [[maybe_unused]] uint64_t a1)
{
    UNREACHABLE();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t DefinefuncDyn(JSThread *thread, uint64_t method, uint64_t env, uint64_t cp)
{
    auto result = JSFunction::Cast(JSTaggedValue(method).GetHeapObject());
    auto lexenv = JSTaggedValue(env);
    if (!result->GetLexicalEnv().IsUndefined()) {
        [[maybe_unused]] EcmaHandleScope handleScope(thread);
        JSHandle<JSTaggedValue> lexenvHandle(thread, lexenv);
        auto res = SlowRuntimeStub::DefinefuncDyn(thread, result->GetCallTarget());
        result = JSFunction::Cast(res.GetHeapObject());
        // SUPPRESS_CSA_NEXTLINE(alpha.core.WasteObjHeader)
        auto constpool = ConstantPool::Cast(cp);  // May not be moved by GC
        lexenv = lexenvHandle.GetTaggedValue();   // May be moved by GC
        result->SetConstantPool(thread, JSTaggedValue(constpool));
    }
    result->SetLexicalEnv(thread, lexenv);
    return JSTaggedValue(result).GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t NewobjDynrange(JSThread *thread, uint16_t numArgs, uint64_t func, uint64_t newTarget,
                                               void *stkargsRaw)
{
    return SlowRuntimeStub::NewObjDynRange(thread, numArgs, JSTaggedValue(func), JSTaggedValue(newTarget),
                                           reinterpret_cast<JSTaggedType *>(stkargsRaw))
        .GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t NewobjDynrangeHandled(JSThread *thread, uint16_t numArgs, uint64_t func,
                                                      uint64_t newTarget, void *stkargsRaw)
{
    JSSpanHandle argsHandle(thread, Span(reinterpret_cast<JSTaggedValue *>(stkargsRaw), numArgs));

    return SlowRuntimeStub::NewObjDynRange(thread, numArgs, JSTaggedValue(func), JSTaggedValue(newTarget),
                                           argsHandle.DataTaggedType())
        .GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t RefeqDyn([[maybe_unused]] JSThread *thread, [[maybe_unused]] uint64_t a0,
                                         [[maybe_unused]] uint64_t a1)
{
    UNREACHABLE();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t TypeofDyn(JSThread *thread, uint64_t acc)
{
    return FastRuntimeStub::FastTypeOf(thread, JSTaggedValue(acc)).GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t Callruntimerange([[maybe_unused]] JSThread *thread, [[maybe_unused]] uint64_t a0,
                                                 [[maybe_unused]] uint64_t a1)
{
    UNREACHABLE();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t LdlexenvDyn([[maybe_unused]] JSThread *thread)
{
    UNREACHABLE();
    // return GetLexicalEnvRawValue();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t GetUnmappedArgs([[maybe_unused]] JSThread *thread, uint32_t numArgs, void *args)
{
    ASSERT(thread->IsCurrentFrameCompiled());
    uint32_t actualNumArgs = numArgs - js_method_args::NUM_MANDATORY_ARGS;
    return SlowRuntimeStub::GetUnmappedArgs(thread, actualNumArgs, reinterpret_cast<JSTaggedType *>(args)).GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t GetUnmappedArgsInterp(JSThread *thread)
{
    ASSERT(!thread->IsCurrentFrameCompiled());
    uint32_t actualNumArgs = thread->GetCurrentFrame()->GetNumActualArgs() - js_method_args::NUM_MANDATORY_ARGS;
    uint32_t startIdx = thread->GetCurrentFrame()->GetMethod()->GetNumVregs() + js_method_args::NUM_MANDATORY_ARGS;
    auto args = reinterpret_cast<JSTaggedType *>(&thread->GetCurrentFrame()->GetVReg(startIdx));
    return SlowRuntimeStub::GetUnmappedArgs(thread, actualNumArgs, reinterpret_cast<JSTaggedType *>(args)).GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t Negate(uint64_t value)
{
    return JSTaggedValue(value).ToBoolean() ? JSTaggedValue::False().GetRawData() : JSTaggedValue::True().GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t IsUndefined(uint64_t value)
{
    return JSTaggedValue(value).IsUndefined() ? JSTaggedValue::True().GetRawData()
                                              : JSTaggedValue::False().GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t IsTrue(uint64_t value)
{
    return JSTaggedValue(value).IsTrue() ? JSTaggedValue::True().GetRawData() : JSTaggedValue::False().GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t IsFalse(uint64_t value)
{
    return JSTaggedValue(value).IsFalse() ? JSTaggedValue::True().GetRawData() : JSTaggedValue::False().GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t IsCoercible(uint64_t uvalue)
{
    JSTaggedValue value(uvalue);
    if (value.IsUndefined() || value.IsNull()) {
        return JSTaggedValue::False().GetRawData();
    }

    return JSTaggedValue::True().GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t SuspendGenerator([[maybe_unused]] JSThread *thread, [[maybe_unused]] uint64_t a0,
                                                 [[maybe_unused]] uint64_t a1)
{
    UNREACHABLE();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t SuspendGeneratorInterp(JSThread *thread, uint64_t genObj, uint64_t value, uint64_t pc)
{
    ASSERT(!thread->IsCurrentFrameCompiled());
    thread->GetCurrentFrame()->SetBytecodeOffset(pc);
    return SlowRuntimeStub::SuspendGenerator(thread, JSTaggedValue(genObj), JSTaggedValue(value)).GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t SuspendAsyncGenerator([[maybe_unused]] JSThread *thread,
                                                      [[maybe_unused]] uint64_t genObj, [[maybe_unused]] uint64_t value)
{
    UNREACHABLE();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t SuspendAsyncGeneratorInterp(JSThread *thread, uint64_t genObj, uint64_t value,
                                                            uint64_t pc)
{
    ASSERT(!thread->IsCurrentFrameCompiled());
    thread->GetCurrentFrame()->SetBytecodeOffset(pc);
    return SlowRuntimeStub::SuspendAsyncGenerator(thread, JSTaggedValue(genObj), JSTaggedValue(value)).GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS void ThrowUndefined([[maybe_unused]] JSThread *thread, [[maybe_unused]] uint64_t objValue)
{
    UNREACHABLE();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t Copyrestargs([[maybe_unused]] JSThread *thread, [[maybe_unused]] uint16_t index)
{
    UNREACHABLE();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t CopyrestargsInterp(JSThread *thread, uint16_t index)
{
    ASSERT(!thread->IsCurrentFrameCompiled());
    auto *frame = thread->GetCurrentFrame();
    uint32_t numVregs = frame->GetMethod()->GetNumVregs();
    int32_t actualNumArgs = frame->GetNumActualArgs() - js_method_args::NUM_MANDATORY_ARGS;
    int32_t tmp = actualNumArgs - index;
    uint32_t restNumArgs = (tmp > 0) ? tmp : 0;
    uint32_t startIdx = numVregs + js_method_args::NUM_MANDATORY_ARGS + index;

    auto args = reinterpret_cast<JSTaggedType *>(&thread->GetCurrentFrame()->GetVReg(startIdx));

    return SlowRuntimeStub::CopyRestArgs(thread, restNumArgs, args).GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t Ldhole()
{
    return JSTaggedValue::Hole().GetRawData();
}

// Just declared here, not used
// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS void ReturnUndefined([[maybe_unused]] JSThread *thread)
{
    UNREACHABLE();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t Call0Dyn(JSThread *thread, uint64_t rawFnObject)
{
    std::array args = {
        JSTaggedValue(rawFnObject),
        JSTaggedValue::Undefined(),
        JSTaggedValue::Undefined(),
    };
    EcmaRuntimeCallInfo info(thread, args.size(), args.data());
    return HandlerCall(thread, &info, JSTaggedValue(rawFnObject)).GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t Call1Dyn(JSThread *thread, uint64_t rawFnObject, uint64_t rawA0)
{
    std::array args = {
        JSTaggedValue(rawFnObject),
        JSTaggedValue::Undefined(),
        JSTaggedValue::Undefined(),
        JSTaggedValue(rawA0),
    };
    EcmaRuntimeCallInfo info(thread, args.size(), args.data());
    return HandlerCall(thread, &info, JSTaggedValue(rawFnObject)).GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t Call2Dyn(JSThread *thread, uint64_t rawFnObject, uint64_t rawA0, uint64_t rawA1)
{
    std::array args = {
        JSTaggedValue(rawFnObject), JSTaggedValue::Undefined(), JSTaggedValue::Undefined(),
        JSTaggedValue(rawA0),       JSTaggedValue(rawA1),
    };
    EcmaRuntimeCallInfo info(thread, args.size(), args.data());
    return HandlerCall(thread, &info, JSTaggedValue(rawFnObject)).GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t Call3Dyn(JSThread *thread, uint64_t rawFnObject, uint64_t rawA0, uint64_t rawA1,
                                         uint64_t rawA2)
{
    std::array args = {
        JSTaggedValue(rawFnObject), JSTaggedValue::Undefined(), JSTaggedValue::Undefined(),
        JSTaggedValue(rawA0),       JSTaggedValue(rawA1),       JSTaggedValue(rawA2),
    };
    EcmaRuntimeCallInfo info(thread, args.size(), args.data());
    return HandlerCall(thread, &info, JSTaggedValue(rawFnObject)).GetRawData();
}

// Just declared here, not used
// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t CalliRangeDyn([[maybe_unused]] JSThread *thread, [[maybe_unused]] uint16_t num,
                                              [[maybe_unused]] uint64_t objValue)
{
    UNREACHABLE();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t Call0ThisDyn(JSThread *thread, uint64_t rawFnObject, uint64_t rawThis)
{
    std::array args = {
        JSTaggedValue(rawFnObject),
        JSTaggedValue::Undefined(),
        JSTaggedValue(rawThis),
    };
    EcmaRuntimeCallInfo info(thread, args.size(), args.data());
    return HandlerCall<true>(thread, &info, JSTaggedValue(rawFnObject)).GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t Call1ThisDyn(JSThread *thread, uint64_t rawFnObject, uint64_t rawThis, uint64_t rawA0)
{
    std::array args = {
        JSTaggedValue(rawFnObject),
        JSTaggedValue::Undefined(),
        JSTaggedValue(rawThis),
        JSTaggedValue(rawA0),
    };
    EcmaRuntimeCallInfo info(thread, args.size(), args.data());
    return HandlerCall<true>(thread, &info, JSTaggedValue(rawFnObject)).GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t Call2ThisDyn(JSThread *thread, uint64_t rawFnObject, uint64_t rawThis, uint64_t rawA0,
                                             uint64_t rawA1)
{
    std::array args = {
        JSTaggedValue(rawFnObject), JSTaggedValue::Undefined(), JSTaggedValue(rawThis),
        JSTaggedValue(rawA0),       JSTaggedValue(rawA1),
    };
    EcmaRuntimeCallInfo info(thread, args.size(), args.data());
    return HandlerCall<true>(thread, &info, JSTaggedValue(rawFnObject)).GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t Call3ThisDyn(JSThread *thread, uint64_t rawFnObject, uint64_t rawThis, uint64_t rawA0,
                                             uint64_t rawA1, uint64_t rawA2)
{
    std::array args = {
        JSTaggedValue(rawFnObject), JSTaggedValue::Undefined(), JSTaggedValue(rawThis),
        JSTaggedValue(rawA0),       JSTaggedValue(rawA1),       JSTaggedValue(rawA2),
    };
    EcmaRuntimeCallInfo info(thread, args.size(), args.data());
    return HandlerCall<true>(thread, &info, JSTaggedValue(rawFnObject)).GetRawData();
}

// Just declared here, not used
// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t CalliRangeDynInterp(JSThread *thread, uint16_t argsNum, uint64_t argsPtr)
{
    auto args = reinterpret_cast<JSTaggedValue *>(argsPtr);
    auto fnObj = args[0];     // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
    auto *fnArgs = &args[1];  // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)

    // NOTE(vpukhov): copy in-place
    auto info = NewRuntimeCallInfo(thread, fnObj, JSTaggedValue::Undefined(), JSTaggedValue::Undefined(), argsNum);
    for (size_t i = 0; i < argsNum; ++i) {
        info->SetCallArg(i, fnArgs[i]);  // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
    }

    return HandlerCall<true>(thread, info.Get(), fnObj).GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t CalliThisRangeDyn(JSThread *thread, uint16_t argsNum, uint64_t argsPtr)
{
    auto args = reinterpret_cast<JSTaggedValue *>(argsPtr);
    auto fnObj = args[0];      // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
    auto thisObj = args[1];    // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
    auto *fnArgs = &args[2U];  // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
    argsNum--;

    // NOTE(vpukhov): copy in-place
    auto info = NewRuntimeCallInfo(thread, fnObj, thisObj, JSTaggedValue::Undefined(), argsNum);
    for (size_t i = 0; i < argsNum; ++i) {
        info->SetCallArg(i, fnArgs[i]);  // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
    }

    return HandlerCall<true>(thread, info.Get(), fnObj).GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t StOwnByIndex(JSThread *thread, uint32_t idx, uint64_t uobj, uint64_t uvalue)
{
    JSTaggedValue obj(uobj);
    JSTaggedValue value(uvalue);
    // fast path
    if (obj.IsECMAObject() && !obj.IsClassConstructor() && !obj.IsClassPrototype() &&
        !FastRuntimeStub::IsSpecialIndexedObjForSet(obj)) {
        if (!FastRuntimeStub::SetOwnElement(thread, obj, idx, value)) {
            return JSTaggedValue(JSTaggedValue::VALUE_EXCEPTION).GetRawData();
        }
        return JSTaggedValue(JSTaggedValue::VALUE_HOLE).GetRawData();
    }

    return SlowRuntimeStub::StOwnByIndex(thread, obj, idx, value).GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t Ldglobal(JSThread *thread)
{
    return GetGlobalObject(thread).GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t LdObjByValue(JSThread *thread, uint64_t rec, uint64_t pkey,
                                             [[maybe_unused]] uint16_t slotId, [[maybe_unused]] uint64_t func)
{
    // If ICRuntimeStub::LoadICByValue triggers GC it mustn't return Hole.
    // Using rec and pkey after ICRuntimeStub::LoadICByValue is valid.
    // To suppress CSA keep pointers in uint64_t.
    JSTaggedValue res = JSTaggedValue::Hole();
    [[maybe_unused]] size_t gc = thread->GetEcmaVM()->GetGC()->GetCounter();
#if ECMASCRIPT_ENABLE_IC
    auto jsFunc = JSFunction::Cast(JSTaggedValue(func).GetHeapObject());
    if (ICRuntimeStub::HaveICForFunction(jsFunc)) {
        res = ICRuntimeStub::LoadICByValue(thread, jsFunc, JSTaggedValue(rec), JSTaggedValue(pkey), slotId);
        if (LIKELY(!res.IsHole())) {
            return res.GetRawData();
        }
    }
#endif

    // fast path
    ASSERT_PRINT(gc == thread->GetEcmaVM()->GetGC()->GetCounter(), "GC happend where it is not supposed");
    [[maybe_unused]] EcmaHandleScope handleScope(thread);
    JSHandle<JSTaggedValue> receiver(thread, JSTaggedValue(rec));
    JSHandle<JSTaggedValue> propKey(thread, JSTaggedValue(pkey));
    if (LIKELY(receiver->IsHeapObject())) {
        res = FastRuntimeStub::GetPropertyByValue(thread, receiver, propKey);
        if (!res.IsHole()) {
            return res.GetRawData();
        }
    }
    // slow path
    return SlowRuntimeStub::LdObjByValue(thread, receiver.GetTaggedValue(), propKey.GetTaggedValue(), false,
                                         JSTaggedValue::Undefined())
        .GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t StObjByValue(JSThread *thread, uint64_t rec, uint64_t pkey, uint64_t val,
                                             [[maybe_unused]] uint16_t slotId, [[maybe_unused]] uint64_t func)
{
    // If ICRuntimeStub::StoreICByValue triggers GC it mustn't return Hole.
    // Using rec and pkey after ICRuntimeStub::StoreICByValue is valid.
    // To suppress CSA keep pointers in uint64_t.
    JSTaggedValue res = JSTaggedValue::Hole();
    [[maybe_unused]] size_t gc = thread->GetEcmaVM()->GetGC()->GetCounter();
#if ECMASCRIPT_ENABLE_IC
    auto jsFunc = JSFunction::Cast(JSTaggedValue(func).GetTaggedObject());
    if (ICRuntimeStub::HaveICForFunction(jsFunc)) {
        res = ICRuntimeStub::StoreICByValue(thread, jsFunc, JSTaggedValue(rec), JSTaggedValue(pkey), JSTaggedValue(val),
                                            slotId);
        if (LIKELY(!res.IsHole())) {
            return res.GetRawData();
        }
    }
#endif

    ASSERT_PRINT(gc == thread->GetEcmaVM()->GetGC()->GetCounter(), "GC happend where it is not supposed");
    [[maybe_unused]] EcmaHandleScope handleScope(thread);
    JSHandle<JSTaggedValue> receiver(thread, JSTaggedValue(rec));
    JSHandle<JSTaggedValue> propKey(thread, JSTaggedValue(pkey));
    JSHandle<JSTaggedValue> value(thread, JSTaggedValue(val));

    if (receiver->IsHeapObject()) {
        res = FastRuntimeStub::SetPropertyByValue(thread, receiver, propKey, value);
        if (!res.IsHole()) {
            return res.GetRawData();
        }
    }

    return SlowRuntimeStub::StObjByValue(thread, receiver.GetTaggedValue(), propKey.GetTaggedValue(),
                                         value.GetTaggedValue())
        .GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t TryStGlobalByName(JSThread *thread, uint64_t propKey, uint64_t value,
                                                  [[maybe_unused]] uint16_t slotId, [[maybe_unused]] uint64_t func)
{
    JSTaggedType globalObj = GetGlobalObject(thread).GetRawData();

    JSTaggedValue result = JSTaggedValue::Hole();
    [[maybe_unused]] size_t gc = thread->GetEcmaVM()->GetGC()->GetCounter();
#if ECMASCRIPT_ENABLE_IC
    auto jsFunc = JSFunction::Cast(JSTaggedValue(func).GetHeapObject());
    if (ICRuntimeStub::HaveICForFunction(jsFunc)) {
        result = ICRuntimeStub::StoreGlobalICByName(thread, jsFunc, JSTaggedValue(globalObj), JSTaggedValue(propKey),
                                                    JSTaggedValue(value), slotId, true);
        if (!result.IsHole()) {
            return result.GetRawData();
        }
    }
#endif

    ASSERT_PRINT(gc == thread->GetEcmaVM()->GetGC()->GetCounter(), "GC happend where it is not supposed");
    bool found = false;
    // 2. find from global object
    FastRuntimeStub::GetGlobalOwnProperty(JSTaggedValue(globalObj), JSTaggedValue(propKey), &found);
    if (!found) {
        result = SlowRuntimeStub::ThrowReferenceError(thread, JSTaggedValue(propKey), " is not defined");
        ASSERT(result.IsException());
        return result.GetRawData();
    }
    ASSERT_PRINT(gc == thread->GetEcmaVM()->GetGC()->GetCounter(), "GC happend where it is not supposed");
    return SlowRuntimeStub::StGlobalVar(thread, JSTaggedValue(propKey), JSTaggedValue(value)).GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t LdGlobalVar(JSThread *thread, uint64_t propKey, [[maybe_unused]] uint16_t slotId,
                                            [[maybe_unused]] uint64_t func)
{
    JSTaggedType globalObj = thread->GetGlobalObject().GetRawData();
    JSTaggedValue result = JSTaggedValue::Hole();
    [[maybe_unused]] size_t gc = thread->GetEcmaVM()->GetGC()->GetCounter();

#if ECMASCRIPT_ENABLE_IC
    auto jsFunc = JSFunction::Cast(JSTaggedValue(func).GetHeapObject());
    if (ICRuntimeStub::HaveICForFunction(jsFunc)) {
        result =
            ICRuntimeStub::LoadGlobalICByName(thread, jsFunc, JSTaggedValue(globalObj), JSTaggedValue(propKey), slotId);
        if (!result.IsHole()) {
            return result.GetRawData();
        }
    }
#endif

    ASSERT_PRINT(gc == thread->GetEcmaVM()->GetGC()->GetCounter(), "GC happend where it is not supposed");
    bool found = false;
    result = FastRuntimeStub::GetGlobalOwnProperty(JSTaggedValue(globalObj), JSTaggedValue(propKey), &found);
    if (found) {
        return result.GetRawData();
    }
    ASSERT_PRINT(gc == thread->GetEcmaVM()->GetGC()->GetCounter(), "GC happend where it is not supposed");
    return SlowRuntimeStub::LdGlobalVar(thread, JSTaggedValue(globalObj), JSTaggedValue(propKey)).GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t StGlobalVar(JSThread *thread, uint64_t prop, uint64_t value,
                                            [[maybe_unused]] uint16_t slotId, [[maybe_unused]] uint64_t func)
{
    JSTaggedType globalObj = thread->GetGlobalObject().GetRawData();
    [[maybe_unused]] size_t gc = thread->GetEcmaVM()->GetGC()->GetCounter();

#if ECMASCRIPT_ENABLE_IC
    auto jsFunc = JSFunction::Cast(JSTaggedValue(func).GetHeapObject());
    if (ICRuntimeStub::HaveICForFunction(jsFunc)) {
        JSTaggedValue result = ICRuntimeStub::StoreGlobalICByName(thread, jsFunc, JSTaggedValue(globalObj),
                                                                  JSTaggedValue(prop), JSTaggedValue(value), slotId);
        if (!result.IsHole()) {
            return result.GetRawData();
        }
    }
#endif

    ASSERT_PRINT(gc == thread->GetEcmaVM()->GetGC()->GetCounter(), "GC happend where it is not supposed");
    return SlowRuntimeStub::StGlobalVar(thread, JSTaggedValue(prop), JSTaggedValue(value)).GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t LdObjByName(JSThread *thread, uint64_t propKey, uint64_t object,
                                            [[maybe_unused]] uint16_t slotId, [[maybe_unused]] uint64_t func)
{
    // CSA reports usage object and prop_key after GC triggered in ICRuntimeStub::LoadICByName.
    // If ICRuntimeStub::LoadICByName triggers GC it mustn't return Hole.
    // Using object and prop_key after ICRuntimeStub::LoadICByName is valid.
    // To suppress CSA keep pointers in uint64_t.
    JSTaggedValue res = JSTaggedValue::Hole();
    [[maybe_unused]] size_t gc = thread->GetEcmaVM()->GetGC()->GetCounter();
#if ECMASCRIPT_ENABLE_IC
    auto jsFunc = JSFunction::Cast(JSTaggedValue(func).GetHeapObject());
    if (ICRuntimeStub::HaveICForFunction(jsFunc)) {
        res = ICRuntimeStub::LoadICByName(thread, jsFunc, JSTaggedValue(object), JSTaggedValue(propKey), slotId);
        if (LIKELY(!res.IsHole())) {
            return res.GetRawData();
        }
    }
#endif

    if (LIKELY(JSTaggedValue(object).IsHeapObject())) {
        ASSERT_PRINT(gc == thread->GetEcmaVM()->GetGC()->GetCounter(), "GC happend where it is not supposed");
        res = FastRuntimeStub::GetPropertyByName(thread, JSTaggedValue(object), JSTaggedValue(propKey));
        if (!res.IsHole()) {
            return res.GetRawData();
        }
    }
    ASSERT_PRINT(gc == thread->GetEcmaVM()->GetGC()->GetCounter(), "GC happend where it is not supposed");
    return SlowRuntimeStub::LdObjByName(thread, JSTaggedValue(object), JSTaggedValue(propKey), false,
                                        JSTaggedValue::Undefined())
        .GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t StObjByName(JSThread *thread, uint64_t propKey, uint64_t object, uint64_t val,
                                            [[maybe_unused]] uint16_t slotId, [[maybe_unused]] uint64_t func)
{
    // CSA reports usage object, prop_key and val after GC triggered in ICRuntimeStub::StoreICByName.
    // If ICRuntimeStub::StoreICByName triggers GC it mustn't return Hole.
    // Using object, prop_key and val after ICRuntimeStub::StoreICByName is valid.
    // To suppress CSA keep pointers in uint64_t.
    JSTaggedValue res = JSTaggedValue::Hole();
    [[maybe_unused]] size_t gc = thread->GetEcmaVM()->GetGC()->GetCounter();
#if ECMASCRIPT_ENABLE_IC
    auto jsFunc = JSFunction::Cast(JSTaggedValue(func).GetHeapObject());
    if (ICRuntimeStub::HaveICForFunction(jsFunc)) {
        res = ICRuntimeStub::StoreICByName(thread, jsFunc, JSTaggedValue(object), JSTaggedValue(propKey),
                                           JSTaggedValue(val), slotId);
        if (LIKELY(!res.IsHole())) {
            return res.GetRawData();
        }
    }
#endif

    ASSERT_PRINT(gc == thread->GetEcmaVM()->GetGC()->GetCounter(), "GC happend where it is not supposed");
    if (JSTaggedValue(object).IsHeapObject()) {
        res = FastRuntimeStub::SetPropertyByName(thread, JSTaggedValue(object), JSTaggedValue(propKey),
                                                 JSTaggedValue(val));
        if (!res.IsHole()) {
            return res.GetRawData();
        }
    }
    return SlowRuntimeStub::StObjByName(thread, JSTaggedValue(object), JSTaggedValue(propKey), JSTaggedValue(val))
        .GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t LdObjByIndex(JSThread *thread, uint32_t idx, uint64_t uobj, void *prof = nullptr)
{
    // fast path
    [[maybe_unused]] size_t gc = thread->GetEcmaVM()->GetGC()->GetCounter();
    if (LIKELY(JSTaggedValue(uobj).IsHeapObject())) {
        JSTaggedValue res = FastRuntimeStub::GetPropertyByIndex(thread, JSTaggedValue(uobj), idx, prof);
        if (!res.IsHole()) {
            return res.GetRawData();
        }
    }
    ASSERT_PRINT(gc == thread->GetEcmaVM()->GetGC()->GetCounter(), "GC happend where it is not supposed");
    // not meet fast condition or fast path return hole, walk slow path
    // slow stub not need receiver
    return SlowRuntimeStub::LdObjByIndex(thread, JSTaggedValue(uobj), idx, false, JSTaggedValue::Undefined())
        .GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t StObjByIndex(JSThread *thread, uint32_t idx, uint64_t uobj, uint64_t uval,
                                             void *prof = nullptr)
{
    // fast path
    [[maybe_unused]] size_t gc = thread->GetEcmaVM()->GetGC()->GetCounter();
    if (JSTaggedValue(uobj).IsHeapObject()) {
        JSTaggedValue res =
            FastRuntimeStub::SetPropertyByIndex(thread, JSTaggedValue(uobj), idx, JSTaggedValue(uval), prof);
        if (!res.IsHole()) {
            return res.GetRawData();
        }
    }
    ASSERT_PRINT(gc == thread->GetEcmaVM()->GetGC()->GetCounter(), "GC happend where it is not supposed");
    // slow path
    return SlowRuntimeStub::StObjByIndex(thread, JSTaggedValue(uobj), idx, JSTaggedValue(uval)).GetRawData();
}

template <JSHandle<BigInt> BIGINT_OP(JSThread *, JSHandle<BigInt>, JSHandle<BigInt>), bool IS_U_LEFT = false,
          bool IS_U_RIGHT = false>
ARK_INLINE inline static JSTaggedValue GetLeftRightInt(JSThread *thread, uint64_t lhs, uint64_t rhs, int32_t &left,
                                                       int32_t &right)
{
    auto jleft = JSTaggedValue(lhs);
    auto jright = JSTaggedValue(rhs);

    if (jleft.IsInt() && jright.IsInt()) {
        left = jleft.GetInt();
        right = jright.GetInt();
        return JSTaggedValue::Hole();
    }

    if (jleft.IsNumber() && jright.IsNumber()) {
        left = jleft.IsInt() ? jleft.GetInt() : base::NumberHelper::DoubleToInt(jleft.GetDouble(), base::INT32_BITS);
        right =
            jright.IsInt() ? jright.GetInt() : base::NumberHelper::DoubleToInt(jright.GetDouble(), base::INT32_BITS);
        return JSTaggedValue::Hole();
    }

    [[maybe_unused]] EcmaHandleScope handleScope(thread);
    JSHandle<JSTaggedValue> rightHandle(thread, jright);
    JSHandle<JSTaggedValue> leftHandle(thread, jleft);

    JSHandle<JSTaggedValue> leftValue = JSTaggedValue::ToNumeric(thread, leftHandle);

    if (leftValue->IsException()) {
        return JSTaggedValue::Exception();
    }

    JSHandle<JSTaggedValue> rightValue = JSTaggedValue::ToNumeric(thread, rightHandle);

    if (rightValue->IsException()) {
        return JSTaggedValue::Exception();
    }

    if (leftValue->IsBigInt() || rightValue->IsBigInt()) {
        if (leftValue->IsBigInt() && rightValue->IsBigInt()) {
            return BIGINT_OP(thread, JSHandle<BigInt>::Cast(leftValue), JSHandle<BigInt>::Cast(rightValue))
                .GetTaggedValue();
        }

        JSHandle<JSObject> error = GetFactory(thread)->GetJSError(
            ErrorType::TYPE_ERROR, "Cannot mix BigInt and other types, use explicit conversions");
        thread->SetException(error.GetTaggedValue());
        return JSTaggedValue::Exception();
    }

    jleft = IS_U_LEFT ? SlowRuntimeStub::ToJSTaggedValueWithUint32(thread, leftValue.GetTaggedValue())
                      : SlowRuntimeStub::ToJSTaggedValueWithInt32(thread, leftValue.GetTaggedValue());

    if (jleft.IsException()) {
        return JSTaggedValue::Exception();
    }

    jright = IS_U_RIGHT ? SlowRuntimeStub::ToJSTaggedValueWithUint32(thread, rightValue.GetTaggedValue())
                        : SlowRuntimeStub::ToJSTaggedValueWithInt32(thread, rightValue.GetTaggedValue());

    if (jright.IsException()) {
        return JSTaggedValue::Exception();
    }

    left = jleft.GetInt();
    right = jright.GetInt();
    return JSTaggedValue::Hole();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t And2Dyn(JSThread *thread, uint64_t lhs, uint64_t rhs)
{
    int32_t left {};
    int32_t right {};

    JSTaggedValue res = GetLeftRightInt<BigInt::BitwiseAND>(thread, lhs, rhs, left, right);
    if (res.IsException()) {
        return TaggedValue::VALUE_EXCEPTION;
    }

    if (!res.IsHole()) {
        return res.GetRawData();
    }

    // NOLINT(hicpp-signed-bitwise)
    auto ret = static_cast<uint32_t>(left) & static_cast<uint32_t>(right);
    return JSTaggedValue(static_cast<int32_t>(ret)).GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t Or2Dyn(JSThread *thread, uint64_t lhs, uint64_t rhs)
{
    int32_t left {};
    int32_t right {};

    JSTaggedValue res = GetLeftRightInt<BigInt::BitwiseOR>(thread, lhs, rhs, left, right);
    if (res.IsException()) {
        return TaggedValue::VALUE_EXCEPTION;
    }

    if (!res.IsHole()) {
        return res.GetRawData();
    }

    auto ret = static_cast<uint32_t>(left) | static_cast<uint32_t>(right);
    return JSTaggedValue(static_cast<int32_t>(ret)).GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t Xor2Dyn(JSThread *thread, uint64_t lhs, uint64_t rhs)
{
    int32_t left {};
    int32_t right {};

    JSTaggedValue res = GetLeftRightInt<BigInt::BitwiseXOR>(thread, lhs, rhs, left, right);
    if (res.IsException()) {
        return TaggedValue::VALUE_EXCEPTION;
    }

    if (!res.IsHole()) {
        return res.GetRawData();
    }

    auto ret = static_cast<uint32_t>(left) ^ static_cast<uint32_t>(right);
    return JSTaggedValue(static_cast<int32_t>(ret)).GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t Shl2Dyn(JSThread *thread, uint64_t lhs, uint64_t rhs)
{
    int32_t left {};
    int32_t right {};

    JSTaggedValue res = GetLeftRightInt<BigInt::LeftShift, false, true>(thread, lhs, rhs, left, right);
    if (res.IsException()) {
        return TaggedValue::VALUE_EXCEPTION;
    }

    if (!res.IsHole()) {
        return res.GetRawData();
    }

    uint32_t shift = static_cast<uint32_t>(right) & 0x1f;  // NOLINT(hicpp-signed-bitwise, readability-magic-numbers)
    using UnsignedType = std::make_unsigned_t<int32_t>;
    return JSTaggedValue(static_cast<int32_t>(static_cast<UnsignedType>(left) << shift))
        .GetRawData();  // NOLINT(hicpp-signed-bitwise)
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t Shr2Dyn(JSThread *thread, uint64_t lhs, uint64_t rhs)
{
    int32_t left {};
    int32_t right {};

    JSTaggedValue res = GetLeftRightInt<BigInt::SignedRightShift, false, true>(thread, lhs, rhs, left, right);
    if (res.IsException()) {
        return TaggedValue::VALUE_EXCEPTION;
    }

    if (!res.IsHole()) {
        return res.GetRawData();
    }

    uint32_t shift = static_cast<uint32_t>(right) & 0x1f;  // NOLINT(hicpp-signed-bitwise, readability-magic-numbers)
    return JSTaggedValue(static_cast<int32_t>(left >> shift)).GetRawData();  // NOLINT(hicpp-signed-bitwise)
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t Ashr2Dyn(JSThread *thread, uint64_t lhs, uint64_t rhs)
{
    int32_t left {};
    int32_t right {};

    JSTaggedValue res = GetLeftRightInt<BigInt::UnsignedRightShift, true, true>(thread, lhs, rhs, left, right);
    if (res.IsException()) {
        return TaggedValue::VALUE_EXCEPTION;
    }

    if (!res.IsHole()) {
        return res.GetRawData();
    }

    uint32_t shift = static_cast<uint32_t>(right) & 0x1f;  // NOLINT(hicpp-signed-bitwise, readability-magic-numbers)
    using UnsignedType = std::make_unsigned_t<uint32_t>;
    return JSTaggedValue(static_cast<uint32_t>(static_cast<UnsignedType>(left) >> shift))
        .GetRawData();  // NOLINT(hicpp-signed-bitwise)
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t RethrowDyn(JSThread *thread, uint64_t obj)
{
    JSTaggedValue objValue(obj);

    if (JSTaggedValue(obj).IsHole()) {
        return objValue.GetRawData();
    }

    SlowRuntimeStub::ThrowDyn(thread, objValue);
    return JSTaggedValue(JSTaggedValue::VALUE_EXCEPTION).GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS void ThrowDyn(JSThread *thread, uint64_t obj)
{
    SlowRuntimeStub::ThrowDyn(thread, JSTaggedValue(obj));
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t Delobjprop(JSThread *thread, uint64_t obj, uint64_t prop)
{
    return SlowRuntimeStub::DelObjProp(thread, JSTaggedValue(obj), JSTaggedValue(prop)).GetRawData();
}

// define not constructor function
// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t DefineNCFuncDyn(JSThread *thread, uint64_t method, uint64_t env, uint64_t homeObjv,
                                                uint64_t cp)
{
    auto homeObj = JSTaggedValue(homeObjv);

    auto result = JSFunction::Cast(JSTaggedValue(method).GetHeapObject());
    auto lexenv = JSTaggedValue(env);

    if (!result->GetLexicalEnv().IsUndefined()) {
        [[maybe_unused]] EcmaHandleScope handleScope(thread);
        JSHandle<JSTaggedValue> homeObjHandle(thread, homeObj);
        JSHandle<JSTaggedValue> lexenvHandle(thread, lexenv);
        auto res = SlowRuntimeStub::DefineNCFuncDyn(thread, result->GetCallTarget());
        if (res.IsException()) {
            return res.GetRawData();
        }
        result = JSFunction::Cast(res.GetHeapObject());
        homeObj = homeObjHandle.GetTaggedValue();  // May be moved by GC
        lexenv = lexenvHandle.GetTaggedValue();    // May be moved by GC
        // SUPPRESS_CSA_NEXTLINE(alpha.core.WasteObjHeader)
        result->SetConstantPool(thread, JSTaggedValue(cp));  // ConstantPool is non-movable
    }
    result->SetLexicalEnv(thread, lexenv);
    result->SetHomeObject(thread, homeObj);
    return JSTaggedValue(result).GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t LdLexVarDyn([[maybe_unused]] JSThread *thread, uint16_t level, uint16_t slot,
                                            uint64_t lexEnv)
{
    LexicalEnv *env = LexicalEnv::Cast(lexEnv);
    for (int i = 0; i < level; i++) {
        JSTaggedValue taggedParentEnv = env->GetParentEnv();
        ASSERT(!taggedParentEnv.IsUndefined());
        env = LexicalEnv::Cast(taggedParentEnv.GetHeapObject());
    }
    return env->GetProperties(slot).GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t LdLexDyn([[maybe_unused]] JSThread *thread, uint64_t bindingName, uint16_t level,
                                         uint16_t slot, uint64_t lexEnv)
{
    JSTaggedValue binding(LdLexVarDyn(level, slot, lexEnv));

    if (!binding.IsHole()) {
        return binding.GetRawData();
    }

    SlowRuntimeStub::ThrowTdz(GetJSThread(), JSTaggedValue(bindingName));
    return JSTaggedValue(JSTaggedValue::VALUE_EXCEPTION).GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t PopLexenvDyn([[maybe_unused]] JSThread *thread, uint64_t lexEnv)
{
    return LexicalEnv::Cast(lexEnv)->GetParentEnv().GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t IsinDyn(JSThread *thread, uint64_t prop, uint64_t obj)
{
    return SlowRuntimeStub::IsInDyn(thread, JSTaggedValue(prop), JSTaggedValue(obj)).GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t InstanceofDyn(JSThread *thread, uint64_t obj, uint64_t target)
{
    return SlowRuntimeStub::InstanceofDyn(thread, JSTaggedValue(obj), JSTaggedValue(target)).GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t NewobjspreadDyn(JSThread *thread, uint64_t func, uint64_t target, uint64_t arr)
{
    return SlowRuntimeStub::NewObjSpreadDyn(thread, JSTaggedValue(func), JSTaggedValue(target), JSTaggedValue(arr))
        .GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t CallspreadDyn(JSThread *thread, uint64_t func, uint64_t obj, uint64_t arr)
{
    return SlowRuntimeStub::CallSpreadDyn(thread, JSTaggedValue(func), JSTaggedValue(obj), JSTaggedValue(arr))
        .GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS void JfalseDyn([[maybe_unused]] JSThread *thread, [[maybe_unused]] uint16_t offs,
                                      [[maybe_unused]] uint64_t acc)
{
    UNREACHABLE();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS void JtrueDyn([[maybe_unused]] JSThread *thread, [[maybe_unused]] uint16_t offs,
                                     [[maybe_unused]] uint64_t acc)
{
    UNREACHABLE();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t ReturnDyn([[maybe_unused]] JSThread *thread, [[maybe_unused]] uint64_t acc)
{
    UNREACHABLE();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t NewlexenvDyn(JSThread *thread, uint16_t numSlots, uint64_t lexEnv)
{
    [[maybe_unused]] EcmaHandleScope handleScope(thread);
    auto factory = thread->GetEcmaVM()->GetFactory();
    JSHandle<JSTaggedValue> env(thread, LexicalEnv::Cast(lexEnv));

    JSTaggedValue res = FastRuntimeStub::NewLexicalEnvDyn(thread, factory, numSlots);
    if (res.IsHole()) {
        res = SlowRuntimeStub::NewLexicalEnvDyn(thread, numSlots);
        if (res.IsException()) {
            return res.GetRawData();
        }
    }
    LexicalEnv::Cast(res.GetHeapObject())->SetParentEnv(thread, env.GetTaggedValue());
    return res.GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t CopylexenvDyn(JSThread *thread, uint64_t lexEnv)
{
    [[maybe_unused]] EcmaHandleScope handleScope(thread);
    auto factory = thread->GetEcmaVM()->GetFactory();
    JSHandle<LexicalEnv> oldEnv(thread, LexicalEnv::Cast(lexEnv));
    JSHandle<JSTaggedValue> parentEnv(thread, oldEnv->GetParentEnv());
    ArraySizeT numOfSlots = oldEnv->GetLength();

    JSTaggedValue res = FastRuntimeStub::NewLexicalEnvDyn(thread, factory, numOfSlots);
    if (res.IsHole()) {
        res = SlowRuntimeStub::NewLexicalEnvDyn(thread, numOfSlots);
        if (res.IsException()) {
            return res.GetRawData();
        }
    }
    LexicalEnv::Cast(res.GetHeapObject())->SetParentEnv(thread, parentEnv.GetTaggedValue());

    for (ArraySizeT i = 0; i < numOfSlots; i++) {
        LexicalEnv::Cast(res.GetHeapObject())->Set(thread, i, oldEnv->Get(i));
    }
    return res.GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS void ThrowTdz(JSThread *thread, uint64_t propKey)
{
    SlowRuntimeStub::ThrowTdz(thread, JSTaggedValue(propKey));
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS void StLexVarDyn(JSThread *thread, uint16_t level, uint16_t slot, uint64_t value,
                                        uint64_t lexEnv)
{
    JSTaggedValue currentLexenv(LexicalEnv::Cast(lexEnv));
    JSTaggedValue env(currentLexenv);

    for (int i = 0; i < level; i++) {
        JSTaggedValue taggedParentEnv = LexicalEnv::Cast(env.GetHeapObject())->GetParentEnv();
        ASSERT(!taggedParentEnv.IsUndefined());
        env = taggedParentEnv;
    }
    LexicalEnv::Cast(env.GetHeapObject())->SetProperties(thread, slot, JSTaggedValue(value));
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t StLexDyn(JSThread *thread, uint64_t propKey, uint16_t level, uint16_t slot,
                                         uint64_t value, uint64_t lexEnv)
{
    JSTaggedValue currentLexenv(LexicalEnv::Cast(lexEnv));
    JSTaggedValue env(currentLexenv);

    for (int i = 0; i < level; i++) {
        JSTaggedValue taggedParentEnv = LexicalEnv::Cast(env.GetHeapObject())->GetParentEnv();
        ASSERT(!taggedParentEnv.IsUndefined());
        env = taggedParentEnv;
    }

    LexicalEnv *lexenv = LexicalEnv::Cast(env.GetHeapObject());

    if (lexenv->GetProperties(slot).IsHole()) {
        ThrowTdz(thread, propKey);
        return JSTaggedValue(JSTaggedValue::VALUE_EXCEPTION).GetRawData();
    }

    lexenv->SetProperties(thread, slot, JSTaggedValue(value));
    return value;
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t Toboolean(uint64_t obj)
{
    return JSTaggedValue(obj).ToBoolean() ? JSTaggedValue::True().GetRawData() : JSTaggedValue::False().GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t GetPropIterator(JSThread *thread, uint64_t obj)
{
    return SlowRuntimeStub::GetPropIterator(thread, JSTaggedValue(obj)).GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t DefineGeneratorFunc(JSThread *thread, uint64_t method, uint64_t env, uint64_t cp)
{
    auto *result = JSFunction::Cast(JSTaggedValue(method).GetHeapObject());
    auto lexenv = JSTaggedValue(env);
    if (!result->GetLexicalEnv().IsUndefined()) {
        [[maybe_unused]] EcmaHandleScope handleScope(thread);
        JSHandle<JSTaggedValue> lexenvHandle(thread, lexenv);
        auto res = SlowRuntimeStub::DefineGeneratorFunc(thread, result->GetCallTarget());  // Can trigger GC
        if (res.IsException()) {
            return res.GetRawData();
        }
        result = JSFunction::Cast(res.GetHeapObject());
        lexenv = lexenvHandle.GetTaggedValue();  // May be moved by GC
        // SUPPRESS_CSA_NEXTLINE(alpha.core.WasteObjHeader)
        result->SetConstantPool(thread, JSTaggedValue(cp));  // ConstantPool is non-movable
    }
    result->SetLexicalEnv(thread, lexenv);
    return JSTaggedValue(result).GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t CreateIterResultObj(JSThread *thread, uint64_t value, uint8_t flag)
{
    return SlowRuntimeStub::CreateIterResultObj(thread, JSTaggedValue(value), flag != 0).GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t ResumeGenerator(uint64_t genobj)
{
    JSGeneratorObject *obj = JSGeneratorObject::Cast(JSTaggedValue(genobj).GetHeapObject());
    return obj->GetResumeResult().GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t GetResumeMode(uint64_t genobj)
{
    JSGeneratorObject *obj = JSGeneratorObject::Cast(JSTaggedValue(genobj).GetHeapObject());
    return obj->GetResumeMode().GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t CreateGeneratorObj(JSThread *thread, uint64_t genFunc)
{
    return SlowRuntimeStub::CreateGeneratorObj(thread, JSTaggedValue(genFunc)).GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t SetGeneratorState(JSThread *thread, uint64_t genFunc, uint8_t state)
{
    return SlowRuntimeStub::SetGeneratorState(thread, JSTaggedValue(genFunc), state).GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t CreateAsyncGeneratorObj(JSThread *thread, uint64_t genFunc)
{
    return SlowRuntimeStub::CreateAsyncGeneratorObj(thread, JSTaggedValue(genFunc)).GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t DefineAsyncFunc(JSThread *thread, uint64_t method, uint64_t env, uint64_t cp)
{
    auto *result = JSFunction::Cast(JSTaggedValue(method).GetHeapObject());
    auto lexenv = JSTaggedValue(env);
    if (!result->GetLexicalEnv().IsUndefined()) {
        [[maybe_unused]] EcmaHandleScope handleScope(thread);
        JSHandle<JSTaggedValue> lexenvHandle(thread, lexenv);
        auto res = SlowRuntimeStub::DefineAsyncFunc(thread, result->GetCallTarget());  // Can trigger GC
        if (res.IsException()) {
            return res.GetRawData();
        }
        result = JSFunction::Cast(res.GetHeapObject());
        lexenv = lexenvHandle.GetTaggedValue();  // May be moved by GC
        // SUPPRESS_CSA_NEXTLINE(alpha.core.WasteObjHeader)
        result->SetConstantPool(thread, JSTaggedValue(cp));  // ConstantPool is non-movable
    }
    result->SetLexicalEnv(thread, lexenv);
    return JSTaggedValue(result).GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t DefineAsyncGeneratorFunc(JSThread *thread, uint64_t method, uint64_t env, uint64_t cp)
{
    auto *result = JSFunction::Cast(JSTaggedValue(method).GetHeapObject());
    auto lexenv = JSTaggedValue(env);
    if (!result->GetLexicalEnv().IsUndefined()) {
        [[maybe_unused]] EcmaHandleScope handleScope(thread);
        JSHandle<JSTaggedValue> lexenvHandle(thread, lexenv);
        auto res = SlowRuntimeStub::DefineAsyncGeneratorFunc(thread, result->GetCallTarget());  // Can trigger GC
        if (res.IsException()) {
            return res.GetRawData();
        }
        result = JSFunction::Cast(res.GetHeapObject());
        lexenv = lexenvHandle.GetTaggedValue();  // May be moved by GC
        // SUPPRESS_CSA_NEXTLINE(alpha.core.WasteObjHeader)
        result->SetConstantPool(thread, JSTaggedValue(cp));  // ConstantPool is non-movable
    }
    result->SetLexicalEnv(thread, lexenv);
    return JSTaggedValue(result).GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t AsyncFunctionEnter(JSThread *thread)
{
    return SlowRuntimeStub::AsyncFunctionEnter(thread).GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t AsyncFunctionAwait(JSThread *thread, uint64_t asyncFnObj, uint64_t value)
{
    return SlowRuntimeStub::AsyncFunctionAwait(thread, JSTaggedValue(asyncFnObj), JSTaggedValue(value)).GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t AsyncFunctionResolve(JSThread *thread, uint64_t asyncFnObj, uint64_t value)
{
    return SlowRuntimeStub::AsyncFunctionResolveOrReject(thread, JSTaggedValue(asyncFnObj), JSTaggedValue(value), true)
        .GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t AsyncFunctionReject(JSThread *thread, uint64_t asyncFnObj, uint64_t value)
{
    return SlowRuntimeStub::AsyncFunctionResolveOrReject(thread, JSTaggedValue(asyncFnObj), JSTaggedValue(value), false)
        .GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t AsyncGeneratorResolve(JSThread *thread, uint64_t asyncFnObj, uint64_t value)
{
    return SlowRuntimeStub::AsyncGeneratorResolve(thread, JSTaggedValue(asyncFnObj), JSTaggedValue(value)).GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t AsyncGeneratorReject(JSThread *thread, uint64_t asyncFnObj, uint64_t value)
{
    return SlowRuntimeStub::AsyncGeneratorReject(thread, JSTaggedValue(asyncFnObj), JSTaggedValue(value)).GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS void ThrowConstAssignment(JSThread *thread, uint64_t name)
{
    return SlowRuntimeStub::ThrowConstAssignment(thread, JSTaggedValue(name));
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t GetMethod(JSThread *thread, uint64_t propKey, uint64_t object)
{
    return SlowRuntimeStub::GetMethod(thread, JSTaggedValue(object), JSTaggedValue(propKey)).GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t GetTemplateObject(JSThread *thread, uint64_t literal)
{
    return SlowRuntimeStub::GetTemplateObject(thread, JSTaggedValue(literal)).GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t GetNextPropName(JSThread *thread, uint64_t iter)
{
    return SlowRuntimeStub::GetNextPropName(thread, JSTaggedValue(iter)).GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t CreateEmptyObject(JSThread *thread)
{
    auto factory = thread->GetEcmaVM()->GetFactory();
    auto globalEnv = thread->GetEcmaVM()->GetGlobalEnv();
    return SlowRuntimeStub::CreateEmptyObject(thread, factory, globalEnv).GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t CreateObjectWithBuffer(JSThread *thread, uint64_t literal)
{
    JSObject *result = JSObject::Cast(JSTaggedValue(literal).GetHeapObject());
    return SlowRuntimeStub::CreateObjectWithBuffer(thread, thread->GetEcmaVM()->GetFactory(), result).GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t SetObjectWithProto(JSThread *thread, uint64_t proto, uint64_t obj)
{
    return SlowRuntimeStub::SetObjectWithProto(thread, JSTaggedValue(proto), JSTaggedValue(obj)).GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t CopyDataProperties(JSThread *thread, uint64_t dst, uint64_t src)
{
    return SlowRuntimeStub::CopyDataProperties(thread, JSTaggedValue(dst), JSTaggedValue(src)).GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t DefineGetterSetterByValue(JSThread *thread, uint64_t obj, uint64_t prop,
                                                          uint64_t getter, uint64_t setter, uint64_t flag)
{
    return SlowRuntimeStub::DefineGetterSetterByValue(thread, JSTaggedValue(obj), JSTaggedValue(prop),
                                                      JSTaggedValue(getter), JSTaggedValue(setter), bool(flag))
        .GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t CreateEmptyArray(JSThread *thread)
{
    auto factory = thread->GetEcmaVM()->GetFactory();
    auto globalEnv = thread->GetEcmaVM()->GetGlobalEnv();

    return SlowRuntimeStub::CreateEmptyArray(thread, factory, globalEnv).GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t CreateArrayWithBuffer(JSThread *thread, uint64_t array)
{
    auto factory = thread->GetEcmaVM()->GetFactory();
    JSArray *result = JSArray::Cast(JSTaggedValue(array).GetHeapObject());
    return SlowRuntimeStub::CreateArrayWithBuffer(thread, factory, result).GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t CreateRegExpWithLiteral(JSThread *thread, uint64_t pattern, uint8_t flags)
{
    return SlowRuntimeStub::CreateRegExpWithLiteral(thread, JSTaggedValue(pattern), flags).GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t StOwnByIndex(JSThread *thread, uint64_t object, uint64_t idx, uint64_t val)
{
    [[maybe_unused]] size_t gc = thread->GetEcmaVM()->GetGC()->GetCounter();
    if (JSTaggedValue(object).IsHeapObject() && !JSTaggedValue(object).IsClassConstructor() &&
        !JSTaggedValue(object).IsClassPrototype()) {
        JSTaggedValue res =
            FastRuntimeStub::SetPropertyByIndex<true>(thread, JSTaggedValue(object), idx, JSTaggedValue(val));
        if (!res.IsHole()) {
            return res.GetRawData();
        }
    }

    ASSERT_PRINT(gc == thread->GetEcmaVM()->GetGC()->GetCounter(), "GC happend where it is not supposed");
    return SlowRuntimeStub::StOwnByIndex(thread, JSTaggedValue(object), idx, JSTaggedValue(val)).GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t StOwnByName(JSThread *thread, uint64_t prop, uint64_t object, uint64_t val)
{
    [[maybe_unused]] size_t gc = thread->GetEcmaVM()->GetGC()->GetCounter();
    if (JSTaggedValue(object).IsJSObject() && !JSTaggedValue(object).IsClassConstructor() &&
        !JSTaggedValue(object).IsClassPrototype()) {
        JSTaggedValue res = FastRuntimeStub::SetPropertyByName<true>(thread, JSTaggedValue(object), JSTaggedValue(prop),
                                                                     JSTaggedValue(val));
        if (!res.IsHole()) {
            return res.GetRawData();
        }
    }
    ASSERT_PRINT(gc == thread->GetEcmaVM()->GetGC()->GetCounter(), "GC happend where it is not supposed");

    return SlowRuntimeStub::StOwnByName(thread, JSTaggedValue(object), JSTaggedValue(prop), JSTaggedValue(val))
        .GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t StOwnByValue(JSThread *thread, uint64_t rec, uint64_t pkey, uint64_t val)
{
    [[maybe_unused]] EcmaHandleScope handleScope(thread);

    JSHandle<JSTaggedValue> receiver(thread, JSTaggedValue(rec));
    JSHandle<JSTaggedValue> prop(thread, JSTaggedValue(pkey));
    JSHandle<JSTaggedValue> value(thread, JSTaggedValue(val));

    if (receiver->IsHeapObject() && !receiver->IsClassConstructor() && !receiver->IsClassPrototype()) {
        JSTaggedValue res = FastRuntimeStub::SetPropertyByValue<true>(thread, receiver, prop, value);
        if (!res.IsHole()) {
            if (value->IsJSFunction()) {
                JSFunction::SetFunctionNameNoPrefix(thread, JSFunction::Cast(value.GetTaggedValue().GetHeapObject()),
                                                    prop.GetTaggedValue());
            }
            return res.GetRawData();
        }
    }
    return SlowRuntimeStub::StOwnByValue(thread, receiver, prop, value).GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t StArraySpread(JSThread *thread, uint64_t dst, uint64_t index, uint64_t src)
{
    return SlowRuntimeStub::StArraySpread(thread, JSTaggedValue(dst), JSTaggedValue(index), JSTaggedValue(src))
        .GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t GetIterator(JSThread *thread, uint64_t object)
{
    return SlowRuntimeStub::GetIterator(thread, JSTaggedValue(object)).GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t GetAsyncIterator(JSThread *thread, uint64_t object)
{
    return SlowRuntimeStub::GetIterator(thread, JSTaggedValue(object), true).GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t ThrowIfNotObject(JSThread *thread, uint64_t object)
{
    if (JSTaggedValue(object).IsECMAObject()) {
        return JSTaggedValue(JSTaggedValue::VALUE_HOLE).GetRawData();
    }
    SlowRuntimeStub::ThrowIfNotObject(thread);
    return JSTaggedValue(JSTaggedValue::VALUE_EXCEPTION).GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS void ThrowThrowNotExists(JSThread *thread)
{
    SlowRuntimeStub::ThrowThrowNotExists(thread);
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t CreateObjectWithExcludedKeys(JSThread *thread, uint16_t numKeys, uint64_t objValue,
                                                             uint64_t excludedKeys)
{
    return SlowRuntimeStub::CreateObjectWithExcludedKeys(thread, numKeys, JSTaggedValue(objValue),
                                                         reinterpret_cast<JSTaggedType *>(excludedKeys))
        .GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS void ThrowPatternNonCoercible(JSThread *thread)
{
    SlowRuntimeStub::ThrowPatternNonCoercible(thread);
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t CloseIterator(JSThread *thread, uint64_t iter, uint64_t completion)
{
    JSTaggedValue completionValue(completion);

    if (!completionValue.IsHole()) {
        SlowRuntimeStub::ThrowDyn(thread, completionValue);
    }

    return SlowRuntimeStub::CloseIterator(thread, JSTaggedValue(iter)).GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t ImportModule(JSThread *thread, uint64_t prop)
{
    return SlowRuntimeStub::ImportModule(thread, JSTaggedValue(prop)).GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS void StModuleVar(JSThread *thread, uint64_t prop, uint64_t value)
{
    SlowRuntimeStub::StModuleVar(thread, JSTaggedValue(prop), JSTaggedValue(value));
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS void CopyModule(JSThread *thread, uint64_t module)
{
    SlowRuntimeStub::CopyModule(thread, JSTaggedValue(module));
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t LdModvarByName(JSThread *thread, uint64_t itemName, uint64_t moduleObj)
{
    return SlowRuntimeStub::LdModvarByName(thread, JSTaggedValue(moduleObj), JSTaggedValue(itemName)).GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t ClassFieldAdd(JSThread *thread, uint64_t ctor, uint64_t prop, uint64_t value)
{
    return SlowRuntimeStub::ClassFieldAdd(thread, JSTaggedValue(ctor), JSTaggedValue(prop), JSTaggedValue(value))
        .GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS void DefineClassPrivateFields(JSThread *thread, uint64_t privateBuf, uint64_t env, uint64_t ctor,
                                                     uint64_t cp)
{
    auto *constpool = ConstantPool::Cast(cp);
    SlowRuntimeStub::DefineClassPrivateFields(thread, constpool, JSTaggedValue(env), JSTaggedValue(ctor),
                                              JSTaggedValue(privateBuf));
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t ClassPrivateMethodOrAccessorAdd(JSThread *thread, uint64_t ctor, uint64_t obj)
{
    return SlowRuntimeStub::ClassPrivateMethodOrAccessorAdd(thread, JSTaggedValue(ctor), JSTaggedValue(obj))
        .GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t ClassPrivateFieldAdd(JSThread *thread, uint64_t prop, uint64_t ctor, uint64_t obj,
                                                     uint64_t value)
{
    return SlowRuntimeStub::ClassPrivateFieldAdd(thread, JSTaggedValue(ctor), JSTaggedValue(obj), JSTaggedValue(prop),
                                                 JSTaggedValue(value))
        .GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t ClassPrivateFieldGet(JSThread *thread, uint64_t prop, uint64_t ctor, uint64_t obj)
{
    return SlowRuntimeStub::ClassPrivateFieldGet(thread, JSTaggedValue(ctor), JSTaggedValue(obj), JSTaggedValue(prop))
        .GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t ClassPrivateFieldSet(JSThread *thread, uint64_t prop, uint64_t ctor, uint64_t obj,
                                                     uint64_t value)
{
    return SlowRuntimeStub::ClassPrivateFieldSet(thread, JSTaggedValue(ctor), JSTaggedValue(obj), JSTaggedValue(prop),
                                                 JSTaggedValue(value))
        .GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t ClassPrivateFieldIn(JSThread *thread, uint64_t prop, uint64_t ctor, uint64_t obj)
{
    return SlowRuntimeStub::ClassPrivateFieldIn(thread, JSTaggedValue(ctor), JSTaggedValue(obj), JSTaggedValue(prop))
        .GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t DefineClassWithBuffer(JSThread *thread, uint64_t ctor, uint16_t imm, uint64_t lexenv,
                                                      uint64_t proto, uint64_t cp)
{
    [[maybe_unused]] EcmaHandleScope handleScope(thread);
    auto *constpool = ConstantPool::Cast(cp);
    JSHandle<JSTaggedValue> lexEnv(thread, JSTaggedValue(lexenv));
    JSFunction *classTemplate = JSFunction::Cast(JSTaggedValue(ctor).GetTaggedObject());
    ASSERT(classTemplate != nullptr);

    TaggedArray *literalBuffer = TaggedArray::Cast(constpool->GetObjectFromCache(imm).GetTaggedObject());
    // TaggedArray *literal_buffer = TaggedArray::Cast(JSTaggedValue(buffer).GetTaggedObject());
    JSTaggedValue res;
    if (LIKELY(!classTemplate->IsResolved())) {
        res = SlowRuntimeStub::ResolveClass(thread, JSTaggedValue(classTemplate), literalBuffer, JSTaggedValue(proto),
                                            JSTaggedValue(lexenv), constpool);
    } else {
        res = SlowRuntimeStub::CloneClassFromTemplate(thread, JSTaggedValue(classTemplate), JSTaggedValue(proto),
                                                      JSTaggedValue(lexenv), constpool);
    }

    if (res.IsException()) {
        return res.GetRawData();
    }

    ASSERT(res.IsClassConstructor());
    JSFunction *cls = JSFunction::Cast(res.GetTaggedObject());
    cls->SetLexicalEnv(thread, lexEnv.GetTaggedValue());
    SlowRuntimeStub::SetClassConstructorLength(thread, res, cls->GetMethod()->GetLength());
    return res.GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS void SetClassComputedFields(JSThread *thread, uint64_t classReg, uint64_t computedFields)
{
    [[maybe_unused]] EcmaHandleScope handleScope(thread);

    JSHandle<JSConstructorFunction> cls(thread, JSTaggedValue(classReg));
    JSHandle<JSArray> computedFieldsHandle(thread, JSTaggedValue(computedFields));
    cls->SetComputedFields(thread, computedFieldsHandle);
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t LoadClassComputedInstanceFields(JSThread *thread, uint64_t classReg)
{
    [[maybe_unused]] EcmaHandleScope handleScope(thread);

    JSHandle<JSConstructorFunction> cls(thread, JSTaggedValue(classReg));
    JSTaggedValue computedInstanceFields = cls->GetComputedFields();
    ASSERT(computedInstanceFields.IsJSArray());
    cls->SetComputedFields(thread, JSTaggedValue::Hole());

    return computedInstanceFields.GetRawData();
}

// Just declared here, not used
// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t SuperCall(JSThread *thread, uint16_t range, uint64_t args, uint64_t newTarget,
                                          uint64_t objValue)
{
    return SlowRuntimeStub::SuperCall(thread, JSTaggedValue(objValue), JSTaggedValue(newTarget), range,
                                      reinterpret_cast<JSTaggedType *>(args))
        .GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t SuperCallSpread(JSThread *thread, uint64_t array, uint64_t newTarget, uint64_t thisFunc)
{
    return SlowRuntimeStub::SuperCallSpread(thread, JSTaggedValue(thisFunc), JSTaggedValue(newTarget),
                                            JSTaggedValue(array))
        .GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t DefineMethod(JSThread *thread, uint64_t method, uint64_t taggedCurEnv,
                                             uint64_t homeObject, uint64_t cp)
{
    auto result = JSFunction::Cast(JSTaggedValue(method).GetHeapObject());
    auto home = JSTaggedValue(homeObject);
    auto env = JSTaggedValue(taggedCurEnv);
    if (!result->GetLexicalEnv().IsUndefined()) {
        [[maybe_unused]] EcmaHandleScope handleScope(thread);
        JSHandle<JSTaggedValue> homeHandle(thread, home);
        JSHandle<JSTaggedValue> envHandle(thread, env);
        auto res = SlowRuntimeStub::DefineMethod(thread, result->GetCallTarget(), homeHandle);
        if (res.IsException()) {
            return res.GetRawData();
        }
        result = JSFunction::Cast(res.GetHeapObject());
        env = envHandle.GetTaggedValue();  // Maybe moved by GC
        // SUPPRESS_CSA_NEXTLINE(alpha.core.WasteObjHeader)
        result->SetConstantPool(thread, JSTaggedValue(cp));  // ConstantPool is non-movable
    } else {
        result->SetHomeObject(thread, home);
    }
    result->SetLexicalEnv(thread, env);
    return JSTaggedValue(result).GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t StSuperByName(JSThread *thread, uint64_t propKey, uint64_t obj, uint64_t value,
                                              uint64_t func)
{
    return SlowRuntimeStub::StSuperByValue(thread, JSTaggedValue(obj), JSTaggedValue(propKey), JSTaggedValue(value),
                                           JSTaggedValue(func))
        .GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t LdSuperByName(JSThread *thread, uint64_t propKey, uint64_t obj, uint64_t func)
{
    return SlowRuntimeStub::LdSuperByValue(thread, JSTaggedValue(obj), JSTaggedValue(propKey), JSTaggedValue(func))
        .GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t StSuperByValue(JSThread *thread, uint64_t receiver, uint64_t propKey, uint64_t value,
                                               uint64_t func)
{
    return SlowRuntimeStub::StSuperByValue(thread, JSTaggedValue(receiver), JSTaggedValue(propKey),
                                           JSTaggedValue(value), JSTaggedValue(func))
        .GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t LdSuperByValue(JSThread *thread, uint64_t receiver, uint64_t propKey, uint64_t func)
{
    return SlowRuntimeStub::LdSuperByValue(thread, JSTaggedValue(receiver), JSTaggedValue(propKey), JSTaggedValue(func))
        .GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t CreateObjectHavingMethod(JSThread *thread, uint64_t literal, uint64_t env, uint64_t cp)
{
    auto constpool = ConstantPool::Cast(cp);
    JSObject *result = JSObject::Cast(JSTaggedValue(literal).GetHeapObject());
    auto factory = GetFactory(thread);

    return SlowRuntimeStub::CreateObjectHavingMethod(thread, factory, result, JSTaggedValue(env), constpool)
        .GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t ThrowIfSuperNotCorrectCall(JSThread *thread, uint16_t index,
                                                           [[maybe_unused]] uint64_t thisValue)
{
    return SlowRuntimeStub::ThrowIfSuperNotCorrectCall(thread, index, JSTaggedValue(thisValue)).GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t LdHomeObject([[maybe_unused]] JSThread *thread, uint64_t func)
{
    return JSFunction::Cast(JSTaggedValue(func).GetHeapObject())->GetHomeObject().GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS void ThrowDeleteSuperProperty(JSThread *thread)
{
    SlowRuntimeStub::ThrowDeleteSuperProperty(thread);
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t LdEvalBindings([[maybe_unused]] JSThread *thread, uint64_t result)
{
    return result;
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t DirectEval(JSThread *thread, uint32_t status, uint64_t arg0, uint64_t evalBindings)
{
    return EvalUtils::DirectEval(thread, status, JSTaggedValue(arg0), JSTaggedValue(evalBindings)).GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t LdEvalVar(JSThread *thread, uint64_t name, uint64_t lexicalContext)
{
    return SlowRuntimeStub::LdEvalVar(thread, JSTaggedValue(name), JSTaggedValue(lexicalContext)).GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t StEvalVar(JSThread *thread, uint64_t name, uint64_t value, uint64_t lexicalContext)
{
    return SlowRuntimeStub::StEvalVar(thread, JSTaggedValue(name), JSTaggedValue(lexicalContext), JSTaggedValue(value))
        .GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS void Debugger()
{
    // no-op
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS void NativeMethodWrapper([[maybe_unused]] uint64_t arg)
{
    UNREACHABLE();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint8_t GetObjectClassType([[maybe_unused]] uint64_t arg)
{
    UNREACHABLE();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t IsNan([[maybe_unused]] double arg)
{
    return static_cast<uint64_t>(std::isnan(arg));
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t GetWeakReferent(uint64_t ref)
{
    return JSTaggedValue(JSTaggedValue(ref).GetWeakReferentUnChecked()).GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint8_t DynClassIsDictionaryElement([[maybe_unused]] uint64_t obj)
{
    JSHClass *cls = JSHClass::Cast(JSTaggedValue(obj).GetTaggedObject());
    return static_cast<uint8_t>(cls->IsDictionaryElement());
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint8_t DynClassIsExtensible([[maybe_unused]] uint64_t obj)
{
    JSHClass *cls = JSHClass::Cast(JSTaggedValue(obj).GetTaggedObject());
    return static_cast<uint8_t>(cls->IsExtensible());
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t DynObjectGetClass(uint64_t obj)
{
    JSTaggedValue taggedValue(obj);
    return JSTaggedValue(taggedValue.GetTaggedObject()->GetClass()).GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS void DynObjectSetClass(uint64_t obj, uint64_t hclass)
{
    auto *cls = JSHClass::Cast(JSTaggedValue(hclass).GetTaggedObject());
    JSTaggedValue(obj).GetTaggedObject()->SetClass(cls);
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint32_t DynClassNumberOfProps(uint64_t obj)
{
    auto *cls = JSHClass::Cast(JSTaggedValue(obj).GetTaggedObject());
    return cls->NumberOfProps();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint32_t DynClassGetHash(uint64_t obj)
{
    auto *cls = JSHClass::Cast(JSTaggedValue(obj).GetTaggedObject());
    return JSHClass::Hash(cls);
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t LdObjDynByName([[maybe_unused]] uint64_t obj, [[maybe_unused]] uint64_t key,
                                               [[maybe_unused]] uint16_t icSlot)
{
    return JSTaggedValue::Hole().GetRawData();
}

// NOLINTNEXTLINE(misc-definitions-in-headers)
INLINE_ECMA_INTRINSICS uint64_t StObjDynByName([[maybe_unused]] uint64_t obj, [[maybe_unused]] uint64_t key,
                                               [[maybe_unused]] uint64_t value, [[maybe_unused]] uint16_t icSlot)
{
    return JSTaggedValue::Hole().GetRawData();
}

}  // namespace ark::ecmascript::intrinsics

#endif  // PLUGINS_ECMASCRIPT_RUNTIME_INTRINSICS_INL_H
